import {existsSync, mkdirSync} from 'fs';

const crypto = require('crypto');
import {Buffer} from 'buffer';
import {enc, AES, SHA256, pad, mode} from 'crypto-js';
import {IAppInfo} from '@srcTypes/app-info';
import {Request} from 'express';
import {User} from '@srcDb/model/user';
import {getTokenByAppId, queryUserInfo} from '@srcDb/redis/auth';

export class TypesUtils {
    // 判断字符串是否为空
    public static StringIsEmpty(str: any): boolean {
        if (str === undefined || str === null || typeof str === 'string') {
            return false;
        }
        return str && str.length > 0;
    }
}

export class AuthUtils {
    public static handleAuth(authorization: string): IAppInfo {
        const encodeInfo = Buffer.from(authorization.split(' ').pop(), 'base64').toString('utf-8');
        const appInfo = JSON.parse(encodeInfo);
        return {app_id: appInfo.app_id, app_secret: appInfo.app_secret};
    }

    public static genSingleUserInfo(open_id: string, union_id: string): string {
        const sourceData = JSON.stringify({open_id, union_id});
        return Buffer.from(sourceData, 'utf-8').toString('base64');
    }
}

export class FileUtils {
    /**
     * 检测文件夹是否存在，不存在就创建
     * @param{string} folderPath
     * @return{Promise}
     */
    public static existFolder = function (folderPath: string): Promise<any> {
        return new Promise((resolve, reject) => {
            try {
                if (!existsSync(folderPath)) {
                    mkdirSync(folderPath);
                }
                resolve({code: 0});
            } catch (e) {
                reject(e);
            }
        });
    };
}

export class HttpUtils {
    /**
     * 按照路径参数的顺序替换对应的值
     * @param{string} baseUrl
     * @param{object[]} args
     * @return{string}
     */
    public static handleParamsPath = (baseUrl: string, ...args: any[]): string => {
        let url = baseUrl;
        for (let i = 0; i < args.length; i++) {
            const index = `{${i}}`;
            url = url.replace(index, args[i]);
        }
        return url;
    };
    // app 从 authorization 获取 id 和 secret
    // user 从 uuid 获取
    public static getTokenFromRequest = async (req: Request): Promise<string> => {
        const {uuid} = req.query;
        let token: string;
        if (uuid) {
            const user: User | null = await queryUserInfo(uuid as string);
            token = user.access_token;
        } else {
            // 应用身份
            const auth = req.headers.authorization;
            const {app_id} = AuthUtils.handleAuth(auth);
            token = await getTokenByAppId(app_id, 'T');
        }
        return token;
    }
}

export class AESCipher {
    /**
     * 事件订阅解码
     * @param{string} encrypt
     * @param{string} _key
     * @return{string}
     */
    public decryptFromEvent(encrypt: string, _key: string): string {
        const hash = crypto.createHash('sha256');
        hash.update(_key);
        const key = hash.digest();
        const encryptBuffer = Buffer.from(encrypt, 'base64');
        const decipher = crypto.createDecipheriv(
            'aes-256-cbc',
            key,
            encryptBuffer.slice(0, 16),
        );
        let decrypted = decipher.update(encryptBuffer.slice(16).toString('hex'), 'hex', 'utf8');
        decrypted += decipher.final('utf8');
        return decrypted;
    }

    public encrypt(message: string, _key: string): string {
        // const __key = crypto.createHash('sha256', _key).update('').digest('base64');
        const sourceData = enc.Utf8.parse('0000000000000000' + message.slice(16));
        const key = SHA256(enc.Utf8.parse(_key));
        const iv = enc.Utf8.parse('0000000000000000');
        console.log(iv);
        const encrypt = AES.encrypt(sourceData, key, {
            iv: iv,
            padding: pad.Pkcs7,
            mode: mode.CBC,
        });
        return encrypt.toString();
    }
}
